package ch.ethz.fcl.metrofont;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Vector;

import static org.lwjgl.opengl.GL15.*;

public class FontBuffer {
	private int size;
	Vector<float[]> texVec;
	Vector<float[]> verVec;
	Vector<float[]> norVec;
	Vector<float[]> moduloVec;

	public int normal_id;
	public int vertex_id;
	public int tex_id;
	public int modulo_id;
	
	public FontBuffer() {
		normal_id = glGenBuffers();
		vertex_id = glGenBuffers();
		tex_id = glGenBuffers();
		modulo_id = glGenBuffers();
		
		norVec = new Vector<float[]>();
		texVec = new Vector<float[]>();
		verVec = new Vector<float[]>();
		moduloVec = new Vector<float[]>();
	}

	public void dispose() {
		glDeleteBuffers(normal_id);
		glDeleteBuffers(vertex_id);
		glDeleteBuffers(tex_id);
		glDeleteBuffers(modulo_id);
		
		texVec.clear();
		verVec.clear();
		norVec.clear();
		moduloVec.clear();
	}

	public void upload() {
		size = texVec.size();

		glBindBuffer(GL_ARRAY_BUFFER, modulo_id);
		glBufferData(GL_ARRAY_BUFFER,
				getBuffer(moduloVec), GL_STATIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		glBindBuffer(GL_ARRAY_BUFFER, normal_id);
		glBufferData(GL_ARRAY_BUFFER, 
				getBuffer(norVec), GL_DYNAMIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		
		glBindBuffer(GL_ARRAY_BUFFER, vertex_id);
		glBufferData(GL_ARRAY_BUFFER, 
				getBuffer(verVec), GL_DYNAMIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		
		glBindBuffer(GL_ARRAY_BUFFER, tex_id);
		glBufferData(GL_ARRAY_BUFFER, 
				getBuffer(texVec), GL_DYNAMIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}

	public FloatBuffer getBuffer(Vector<float[]> vec) {
		if (vec == null)
			return null;
		ByteBuffer bb = ByteBuffer.allocateDirect(vec.size()
				* vec.get(0).length * 8);
		bb.order(ByteOrder.nativeOrder());
		FloatBuffer buffer = bb.asFloatBuffer();
		
		for (int i = 0; i < vec.size(); i++) {
			float[] tex = vec.get(i);
			for (int j = 0; j < tex.length; j++)
				buffer.put(tex[j]);
		}
		
		buffer.position(0);
		return buffer;
	}

	public void uploadNormals(float[][] normals) {
		if (norVec == null)
			norVec = new Vector<float[]>();
		for (int i = 0; i < normals.length; i++)
			norVec.add(normals[i]);
	}

	public void uploadVertices(float[][] vertices) {
		if (verVec == null)
			verVec = new Vector<float[]>();
		for (int i = 0; i < vertices.length; i++)
			verVec.add(vertices[i]);
	}

	public void uploadTex(float[][] texCoor) {
		if (texVec == null)
			texVec = new Vector<float[]>();
		for (int i = 0; i < texCoor.length; i++)
			texVec.add(texCoor[i]);
	}

	public void uploadModulo(float[][] modulo) {
		if (moduloVec == null)
			moduloVec = new Vector<float[]>();
		for (int i = 0; i < modulo.length; i++)
			moduloVec.add(modulo[i]);
	}

	public int size() {
		return size;
	}
}
